//唐崇展、曾凡诚
#include "Simulator.h"
#include "Schedule/Scheduler.h" // 包含Scheduler头文件，用于初始化指针
#include <QDebug>

// 构造函数：初始化Scheduler指针（传入Simulator实例）、DataManager，绑定信号
Simulator::Simulator(QObject* parent) :
    QObject(parent),
    globalTime(0),
    scheduler(new Scheduler(this, "经济调度", this)),
    dataMgr(new DataManager(this)) // 修改：Scheduler改为指针，传入当前Simulator实例
{
    // 连接柴油发电机数据信号
    connect(dataMgr, &DataManager::dieselGenTimePowerLoaded,
            this, &Simulator::onDieselGenTimePowerLoaded);
    // 连接光伏数据信号
    connect(dataMgr, &DataManager::pvDataLoaded,
            this, &Simulator::onPvDataLoaded);
    // 新增：连接储能、负载、电网数据信号
    connect(dataMgr, &DataManager::energyStorageDataLoaded,
            this, &Simulator::onEnergyStorageDataLoaded);
    connect(dataMgr, &DataManager::loadDataLoaded,
            this, &Simulator::onLoadDataLoaded);
    connect(dataMgr, &DataManager::gridDataLoaded,
            this, &Simulator::onGridDataLoaded);
    // 新增：连接电价数据信号
    connect(dataMgr, &DataManager::gPriceDataLoaded,
            this, &Simulator::onGPriceDataLoaded);
    // 连接失败信号
    connect(dataMgr, &DataManager::importFailed,
            this, [=](const QString& reason){
                qDebug() << "CSV导入失败：" << reason; // 修正日志：不局限于柴油发电机
            });

    // 新增：连接Simulator时间推进信号到Scheduler调度槽函数
    connect(this, &Simulator::simulationStepAdvanced,
            scheduler, &Scheduler::onSimulationTime);

    initializeSystem();
}

// 新增：析构函数（释放Scheduler和DataManager指针，避免内存泄漏）
Simulator::~Simulator()
{
    delete scheduler;
    delete dataMgr; // dataMgr为构造函数中new的对象，需手动释放
}

void Simulator::initializeSystem() {
    currentState.componentParams.clear();
    currentState.componentParams.push_back(ComponentParam(1, "光伏", 0.0f, 0.0f));
    currentState.componentParams.push_back(ComponentParam(2, "储能", 0.0f, 0.0f));
    currentState.componentParams.push_back(ComponentParam(3, "储能", 0.0f, 0.0f));
    currentState.componentParams.push_back(ComponentParam(4, "电网", 0.0f, 0.0f));
    currentState.componentParams.push_back(ComponentParam(5, "电网", 0.0f, 0.0f));
    currentState.componentParams.push_back(ComponentParam(6, "电网", 0.0f, 0.0f));

    currentState.soc = 0.0f; // 修正：初始SOC设为0（原0.5f）

    // 遍历所有组件ID，匹配对应映射表设置时间0的初始值（电价ID=6注释修正）
    for (auto& param : currentState.componentParams) {
        QMap<int, float>* targetMap = nullptr;
        // 根据组件ID绑定对应的“时间-值”映射表（电价为价格，非功率）
        switch (param.id) {
        case 1: targetMap = &pvTimePowerMap; break;       // 光伏（ID=1，时间→功率）
        case 2: targetMap = &energyStorageTimePowerMap; break; // 储能（ID=2，时间→功率）
        case 3: targetMap = &dieselGenTimePowerMap; break; // 柴油发电机（ID=3，时间→功率）
        case 4: targetMap = &loadTimePowerMap; break;     // 负载（ID=4，时间→功率）
        case 5: targetMap = &gridTimePowerMap; break;     // 电网（ID=5，时间→功率）
        case 6: targetMap = &gPriceTimePriceMap; break;   // 电价（ID=6，时间→价格，非功率）
        default: break;
        }
        // 若映射表存在且包含时间0的数据，更新组件初始值
        if (targetMap != nullptr && targetMap->contains(0)) {
            param.currentPower = (*targetMap)[0]; // 电价复用currentPower字段存储价格
            qDebug() << "组件ID=" << param.id << "（" << param.type << "）初始值（时间0）：" << param.currentPower;
        }
    }
}

// 修改：启动仿真总步数改为24（0-23），移除results相关逻辑
void Simulator::startSimulation(int stepSec) {
    qDebug() << "启动仿真，步长：" << stepSec << "秒（目标1小时=3600秒），时间步范围：0-23";

    globalTime = 0; // 重置全局时间为0（起始点）
    // 移除：不再使用ScheduleResult，删除结果清空逻辑
    // results.clear();

    // 总步数改为24（覆盖0-23所有时间点）
    int totalSteps = 24;

    for (int i = 0; i < totalSteps; ++i) {
        advanceTimeStep();
        emit simulationStepAdvanced(globalTime); // 发射时间推进信号，触发Scheduler调度
    }
}

void Simulator::setInitialParams(const QList<ComponentParam>& params) {
    // 保留参数设置逻辑（不影响时间测试，可选注释）
    qDebug() << "设置仿真初始参数，组件数：" << params.size();

    currentState.componentParams.clear();
    for (const auto& p : params) {
        currentState.componentParams.push_back(p);
        qDebug() << "组件ID：" << p.id << " 功率/价格：" << p.currentPower; // 修正：适配电价的价格字段
    }
}

void Simulator::advanceTimeStep() {
    if (globalTime >= 23) return; // 修正：时间步上限23，避免超出0-23范围
    // 更新时间相关状态（保留：全局时间核心逻辑）
    globalTime++;
    currentState.currentTime = globalTime;

    // 遍历所有组件ID，根据当前时间更新值（电价ID=6注释修正）
    for (auto& param : currentState.componentParams) {
        QMap<int, float>* targetMap = nullptr;
        // 根据组件ID绑定对应的“时间-值”映射表
        switch (param.id) {
        case 1: targetMap = &pvTimePowerMap; break;       // 光伏（ID=1，时间→功率）
        case 2: targetMap = &energyStorageTimePowerMap; break; // 储能（ID=2，时间→功率）
        case 3: targetMap = &dieselGenTimePowerMap; break; // 柴油发电机（ID=3，时间→功率）
        case 4: targetMap = &loadTimePowerMap; break;     // 负载（ID=4，时间→功率）
        case 5: targetMap = &gridTimePowerMap; break;     // 电网（ID=5，时间→功率）
        case 6: targetMap = &gPriceTimePriceMap; break;   // 电价（ID=6，时间→价格）
        default: break;
        }
        // 若映射表存在且包含当前时间的数据，更新组件值
        if (targetMap != nullptr && targetMap->contains(currentState.currentTime)) {
            float newValue = (*targetMap)[currentState.currentTime];
            param.currentPower = newValue;
            qDebug() << "时间点=" << currentState.currentTime
                     << " 组件ID=" << param.id << "（" << param.type << "）值更新为：" << newValue;
        }
    }
}

// 修正：注释改为“回退时间步”，逻辑保留
void Simulator::backTimeStep() {
    // 更新时间相关状态（保留：全局时间核心逻辑）
    if (globalTime <= 0) return; // 时间步下限0，避免低于起始点
    globalTime--;
    currentState.currentTime = globalTime;

    // 遍历所有组件ID，根据当前时间更新值（电价ID=6注释修正）
    for (auto& param : currentState.componentParams) {
        QMap<int, float>* targetMap = nullptr;
        // 根据组件ID绑定对应的“时间-值”映射表
        switch (param.id) {
        case 1: targetMap = &pvTimePowerMap; break;       // 光伏（ID=1，时间→功率）
        case 2: targetMap = &energyStorageTimePowerMap; break; // 储能（ID=2，时间→功率）
        case 3: targetMap = &dieselGenTimePowerMap; break; // 柴油发电机（ID=3，时间→功率）
        case 4: targetMap = &loadTimePowerMap; break;     // 负载（ID=4，时间→功率）
        case 5: targetMap = &gridTimePowerMap; break;     // 电网（ID=5，时间→功率）
        case 6: targetMap = &gPriceTimePriceMap; break;   // 电价（ID=6，时间→价格）
        default: break;
        }
        // 若映射表存在且包含当前时间的数据，更新组件值
        if (targetMap != nullptr && targetMap->contains(currentState.currentTime)) {
            float newValue = (*targetMap)[currentState.currentTime];
            param.currentPower = newValue;
            qDebug() << "时间点=" << currentState.currentTime
                     << " 组件ID=" << param.id << "（" << param.type << "）值更新为：" << newValue;
        }
    }
}

int Simulator::getCurrentTime() const {
    return globalTime; // 保留时间获取接口
}

// 移除：不再使用ScheduleResult，删除该函数（头文件已同步移除）
// const std::vector<ScheduleResult>& Simulator::getResults() const {
//     return results; // 虽然暂时不用，但保留接口避免编译错误
// }

// 槽函数：接收 DataManager 传递的“时间→功率”映射（柴油发电机）
void Simulator::onDieselGenTimePowerLoaded(QMap<int, float> timeToPower) {
    dieselGenTimePowerMap = timeToPower;
    qDebug() << "Simulator 已接收柴油发电机数据，时间点数量：" << timeToPower.size();
    qDebug()<<"simulator____jieshou";
}

// 槽函数：接收 DataManager 传递的“时间→功率”映射（光伏）
void Simulator::onPvDataLoaded(const QMap<int, float> pvTimePower) {
    this->pvTimePowerMap = pvTimePower; // 存储光伏的“时间-功率”映射
    qDebug() << "Simulator 已接收光伏数据，共" << pvTimePower.size() << "个时间点";
}

// 新增：槽函数（接收储能数据）
void Simulator::onEnergyStorageDataLoaded(const QMap<int, float>& esTimePower) {
    energyStorageTimePowerMap = esTimePower;
    qDebug() << "Simulator 已接收储能数据，共" << esTimePower.size() << "个时间点";
}

// 新增：槽函数（接收负载数据）
void Simulator::onLoadDataLoaded(const QMap<int, float>& loadTimePower) {
    loadTimePowerMap = loadTimePower;
    qDebug() << "Simulator 已接收负载数据，共" << loadTimePower.size() << "个时间点";
}

// 新增：槽函数（接收电网数据）
void Simulator::onGridDataLoaded(const QMap<int, float>& gridTimePower) {
    gridTimePowerMap = gridTimePower;
    qDebug() << "Simulator 已接收电网数据，共" << gridTimePower.size() << "个时间点";
}

// 新增：槽函数（接收电价数据）
void Simulator::onGPriceDataLoaded(const QMap<int, float>& gPriceTimePrice) {
    gPriceTimePriceMap = gPriceTimePrice;
    qDebug() << "Simulator 已接收电价数据，共" << gPriceTimePrice.size() << "个时间点";
}

